package com.ia.aistream.common.utils.http;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * Servlet相关工具类
 *
 * @author: chenjunsheng
 */
@Slf4j
public class HttpServletUtils {

    private static final String[] HEDER_NAME_KEY = {"x-forwarded-for", "HTTP_X_FORWARDED_FOR", "Proxy-Client-IP", "WL-Proxy-Client-IP", "HTTP_CLIENT_IP", "X-Real-IP", "x-real-ip"};
    private static final List<IPRange> INNER_IP_LIST = Lists.newArrayList();

    static {
        INNER_IP_LIST.add(new IPRange("127.0.0.0", "127.255.255.255"));
        INNER_IP_LIST.add(new IPRange("10.0.0.0", "10.255.255.255"));
        INNER_IP_LIST.add(new IPRange("172.16.0.0", "172.31.255.255"));
        INNER_IP_LIST.add(new IPRange("192.168.0.0", "192.168.255.255"));
    }

    /**
     * 获取IP V4 的地址
     *
     * @param request HttpServletRequest
     * @return ip v4 的地址
     */
    public static String getRemoteIp(HttpServletRequest request) {
        String ip = request.getRemoteAddr();
        if (StringUtils.isNotEmpty(ip)) {
            // ipv6 暂时直接返回
            if (ip.contains(":") && !"0:0:0:0:0:0:0:1".equalsIgnoreCase(ip)) {
                return ip;
            } else if (!ip.contains(":") && isPublicNetworkIp(ip)) {
                return ip;
            }
        }

        for (String headerNameKey : HEDER_NAME_KEY) {
            ip = request.getHeader(headerNameKey);
            if (StringUtils.isEmpty(ip)) {
                continue;
            }

            if ("unknown".equalsIgnoreCase(ip)) {
                continue;
            }

            ip = ip.split(",")[0];
            if (ip.contains(":")) {
                return ip;
            }

            if (isPublicNetworkIp(ip)) {
                return ip;
            }
        }

        return request.getRemoteAddr();
    }


    /**
     * 读取请求信息
     *
     * @param request
     * @return
     * @throws IOException
     */
    public static String getBody(HttpServletRequest request) throws IOException {
        StringBuilder buffer = new StringBuilder();
        String line;
        try (BufferedReader reader = request.getReader()) {
            line = reader.readLine();
            while (line != null) {
                buffer.append(line);
                line = reader.readLine();
            }
            return buffer.toString();
        } catch (IOException e) {
            throw e;
        }
    }

    /**
     * 获取HttpServletRequest 请求参数
     *
     * @param request
     * @return
     */
    public static String getParameterStr(HttpServletRequest request) {
        Map<String, String[]> parameterMap = request.getParameterMap();
        Iterator<String> iterator = parameterMap.keySet().iterator();
        StringBuilder builder = new StringBuilder();
        while (iterator.hasNext()) {
            String key = iterator.next();
            String value = request.getParameter(key);
            //处理你得到的参数名与值
            builder.append(key).append("=").append(value).append("&");
        }

        if (builder.length() == 0) {
            return "";
        }
        return builder.substring(0, builder.length() - 1);
    }

    /**
     * 获取HttpServletRequest 请求参数
     *
     * @param request
     * @return
     */
    public static Map<String, String> getParameterMap(HttpServletRequest request) {
        Map<String, String[]> parameterMap = request.getParameterMap();
        Iterator<String> iterator = parameterMap.keySet().iterator();
        Map<String, String> param = new HashMap<>();
        String key;
        String value;
        while (iterator.hasNext()) {
            key = iterator.next();
            value = request.getParameter(key);
            param.put(key, value);
        }

        return param;
    }

    /**
     * 返回json数据
     *
     * @param response
     * @param object
     */
    public static void writeJson(HttpServletResponse response, Object object) throws IOException {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        try (PrintWriter out = response.getWriter()) {
            out.append(JSON.toJSONString(object));
            out.flush();
        } catch (IOException e) {
            throw e;
        }
    }

    /**
     * 判断IP是否为私有IP：
     * A类  10.0.0.0-10.255.255.255
     * B类  172.16.0.0-172.31.255.255
     * C类  192.168.0.0-192.168.255.255
     * 当然，还有127这个网段是环回地址
     *
     * @param ip ip地址
     * @return true, IP为私有IP；false, IP不是私有IP
     */
    private static boolean isPublicNetworkIp(String ip) {
        long ipLong = ip2Long(ip);
        for (IPRange range : INNER_IP_LIST) {
            if (range.ipStart <= ipLong && ipLong <= range.ipEnd) {
                return false;
            }
        }
        return true;
    }

    /**
     * IP地址转long类型
     *
     * @param ip
     * @return
     */
    private static long ip2Long(String ip) {
        String[] ipParts = ip.split("\\.");
        long iplong = 0L;
        for (int i = 0; i < 4; ++i) {
            iplong = iplong << 8 | Integer.parseInt(ipParts[i]);
        }
        return iplong;
    }

    private static final class IPRange {
        private long ipStart;
        private long ipEnd;

        private IPRange(String ipStart, String ipEnd) {
            this.ipStart = ip2Long(ipStart);
            this.ipEnd = ip2Long(ipEnd);
            if (this.ipStart > this.ipEnd) {
                long temp = this.ipStart;
                this.ipStart = this.ipEnd;
                this.ipEnd = temp;
            }
        }
    }


}
